package com.eightbears.beboy.ui.chat.ui.fragment;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.eightbears.beboy.MainActivity;
import com.eightbears.beboy.R;
import com.eightbears.beboy.base.cache.TopUserCache;
import com.eightbears.beboy.base.util.ShowToast;
import com.eightbears.beboy.entity.event.TopUserEvent;
import com.eightbears.beboy.ui.chat.ui.activity.GroupDetailsActivity;
import com.eightbears.beboy.ui.chat.widget.EaseConversationList;
import com.eightbears.beboy.ui.user.activity.ContactsListActivity;
import com.eightbears.beboy.ui.user.activity.NeartyPeopleActivity;
import com.eightbears.greendao.TopEaseUser;
import com.hyphenate.EMConnectionListener;
import com.hyphenate.EMConversationListener;
import com.hyphenate.EMError;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMConversation;
import com.hyphenate.chat.EMMessage;
import com.hyphenate.easeui.ui.EaseBaseFragment;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import butterknife.ButterKnife;

import static com.eightbears.beboy.MainActivity.EVENT_ADD_FRIENDS;
import static com.eightbears.beboy.R.id;
import static com.eightbears.beboy.R.layout;
import static com.eightbears.beboy.ui.merchant.activity.ReservationShopActivity.EVENT_RESERVATION_SUCCESS;

/**
 * conversation list fragment
 */
public class EaseConversationListFragment extends EaseBaseFragment {
    private final static int MSG_REFRESH = 2;

    protected EditText query;
    protected ImageButton clearSearch;
    protected boolean hidden;

    protected List<EMConversation> conversationList = new ArrayList<EMConversation>();
    protected EaseConversationList conversationListView;
    protected FrameLayout errorItemContainer;
    protected ImageView iv_unread;

    protected boolean isConflict;
    public Map<String, TopEaseUser> topMap;
    private List<EMConversation> topList = new ArrayList<>();

    protected EMConversationListener convListener = new EMConversationListener() {

        @Override
        public void onCoversationUpdate() {
            refresh();
        }
    };

    protected RelativeLayout rl_no_message;
    protected RelativeLayout mRl_near;
    private TextView mTv_chat;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(layout.ease_fragment_conversation_list, container, false);
        ButterKnife.bind(this, view);
        EventBus.getDefault().register(this);
        MainActivity parentActivity = (MainActivity) getActivity();
        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        if (savedInstanceState != null && savedInstanceState.getBoolean("isConflict", false))
            return;
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    protected void initView() {
        inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
        conversationListView = (EaseConversationList) getView().findViewById(id.list);
        getView().findViewById(id.search_bar_view).setVisibility(View.GONE);
        mRl_near = (RelativeLayout) getView().findViewById(id.rl_near);
        query = (EditText) getView().findViewById(id.query);
        clearSearch = (ImageButton) getView().findViewById(id.search_clear);  // button to clear content in search bar
        rl_no_message = (RelativeLayout) getView().findViewById(R.id.rl_no_message);
        errorItemContainer = (FrameLayout) getView().findViewById(id.fl_error_item);
        mTv_chat = (TextView) getView().findViewById(id.tv_chat);
        iv_unread = (ImageView) getView().findViewById(id.iv_unread);
    }

    @Override
    protected void setUpView() {
        topMap = TopUserCache.getInstance(getContext()).getTopUsers();
        conversationList.addAll(loadConversationList());
        conversationListView.init(conversationList, topList, topMap);

        if (listItemClickListener != null) {
            conversationListView.setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    EMConversation conversation = conversationListView.getItem(position);
                    listItemClickListener.onListItemClicked(conversation);
                }
            });
        }

        if (conversationListView.getAdapter().getCount() == 0) {
            rl_no_message.setVisibility(View.VISIBLE);
            conversationListView.setVisibility(View.GONE);
        } else {
            rl_no_message.setVisibility(View.GONE);
            conversationListView.setVisibility(View.VISIBLE);
        }

        EMClient.getInstance().addConnectionListener(connectionListener);

        query.addTextChangedListener(new TextWatcher() {
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                conversationListView.filter(s);
                if (s.length() > 0) {
                    clearSearch.setVisibility(View.VISIBLE);
                } else {
                    clearSearch.setVisibility(View.INVISIBLE);
                }
            }

            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            public void afterTextChanged(Editable s) {
            }
        });

        clearSearch.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                query.getText().clear();
                hideSoftKeyboard();
            }
        });

        conversationListView.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                hideSoftKeyboard();
                return false;
            }
        });

        mTv_chat.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getActivity(), ContactsListActivity.class));
                getActivity().overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out);
            }
        });


    }


    protected EMConnectionListener connectionListener = new EMConnectionListener() {
        @Override
        public void onDisconnected(int error) {
            if (error == EMError.USER_REMOVED || error == EMError.USER_LOGIN_ANOTHER_DEVICE || error == EMError.SERVER_SERVICE_RESTRICTED) {
                isConflict = true;
            } else {
                handler.sendEmptyMessage(0);
            }
        }

        @Override
        public void onConnected() {
            handler.sendEmptyMessage(1);
        }
    };
    private EaseConversationListItemClickListener listItemClickListener;

    protected Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case 0:
                    onConnectionDisconnected();
                    break;
                case 1:
                    onConnectionConnected();
                    break;

                case MSG_REFRESH: {
                    conversationList.clear();
                    topMap = TopUserCache.getInstance(getContext()).getTopUsers();
                    List<EMConversation> conversations = loadConversationList();
                    conversationList.addAll(conversations);
                    conversationListView.init(conversationList, topList, topMap);
                    if (conversationListView.getAdapter().getCount() == 0) {
                        rl_no_message.setVisibility(View.VISIBLE);
                        conversationListView.setVisibility(View.GONE);
                    } else {
                        rl_no_message.setVisibility(View.GONE);
                        conversationListView.setVisibility(View.VISIBLE);
                    }
                    if (null != conversationListView)
                        conversationListView.refresh();
                    break;
                }
                default:
                    break;
            }
        }
    };

    /**
     * connected to server
     */
    protected void onConnectionConnected() {
        errorItemContainer.setVisibility(View.GONE);
    }

    /**
     * disconnected with server
     */
    protected void onConnectionDisconnected() {
        errorItemContainer.setVisibility(View.VISIBLE);
    }


    /**
     * refresh ui
     */
    public void refresh() {
        if (!handler.hasMessages(MSG_REFRESH)) {
            handler.sendEmptyMessage(MSG_REFRESH);
        }
    }

    /**
     * load conversation list
     *
     * @return +
     */
    protected List<EMConversation> loadConversationList() {
        // get all conversations
        Map<String, EMConversation> conversations = EMClient.getInstance().chatManager().getAllConversations();
        List<Pair<Long, EMConversation>> sortList = new ArrayList<>();
        List<EMConversation> top_list = new ArrayList<>();
        /**
         * lastMsgTime will change if there is new message during sorting
         * so use synchronized to make sure timestamp of last message won't change.
         */
        synchronized (conversations) {
            for (EMConversation conversation : conversations.values()) {
                if (conversation.getAllMessages().size() != 0) {
                    if (null != topMap && !topMap.containsKey(conversation.getExtField())) {
                        sortList.add(new Pair<>(conversation.getLastMessage().getMsgTime(), conversation));
                    } else {
                        top_list.add(conversation);
                    }
                }
            }
        }

        topList.clear();
        topList.addAll(top_list);

        try {
            // Internal is TimSort algorithm, has bug
            sortConversationByLastChatTime(sortList);
            sortConversationByLastChatTimes(topList);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<EMConversation> list = new ArrayList<EMConversation>();
        for (Pair<Long, EMConversation> sortItem : sortList) {
            list.add(sortItem.second);
        }
        return list;
    }

    /**
     * sort conversations according time stamp of last message
     *
     * @param conversationList
     */
    private void sortConversationByLastChatTime(List<Pair<Long, EMConversation>> conversationList) {
        Collections.sort(conversationList, new Comparator<Pair<Long, EMConversation>>() {
            @Override
            public int compare(final Pair<Long, EMConversation> con1, final Pair<Long, EMConversation> con2) {

                if (con1.first.equals(con2.first)) {
                    return 0;
                } else if (con2.first.longValue() > con1.first.longValue()) {
                    return 1;
                } else {
                    return -1;
                }
            }

        });
    }

    private void sortConversationByLastChatTimes(List<EMConversation> conversationList) {
        Collections.sort(conversationList, new Comparator<EMConversation>() {
            @Override
            public int compare(EMConversation lhs, EMConversation rhs) {
                EMMessage con2LastMessage = rhs.getLastMessage();
                EMMessage con1LastMessage = lhs.getLastMessage();
                if (con2LastMessage.getMsgTime() == con1LastMessage.getMsgTime()) {
                    return 0;
                } else if (con2LastMessage.getMsgTime() > con1LastMessage.getMsgTime()) {
                    return 1;
                } else {
                    return -1;
                }

            }
        });
    }

    protected void hideSoftKeyboard() {
        if (getActivity().getWindow().getAttributes().softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) {
            if (getActivity().getCurrentFocus() != null)
                inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(),
                        InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        this.hidden = hidden;
        if (!hidden && !isConflict) {
            refresh();
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!hidden) {
            refresh();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
        EMClient.getInstance().removeConnectionListener(connectionListener);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (isConflict) {
            outState.putBoolean("isConflict", true);
        }
    }

    public interface EaseConversationListItemClickListener {
        /**
         * click event for conversation list
         *
         * @param conversation -- clicked item
         */
        void onListItemClicked(EMConversation conversation);
    }

    /**
     * set conversation list item click listener
     *
     * @param listItemClickListener
     */
    public void setConversationListItemClickListener(EaseConversationListItemClickListener listItemClickListener) {
        this.listItemClickListener = listItemClickListener;
    }


    @Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
    public void onTopUser(TopUserEvent topUserEvent) {
        if (-1 == topUserEvent.getPostion()) {
            EMClient.getInstance().chatManager().deleteConversation(topUserEvent.getUsername(), true);
            ShowToast.showShortToast(getString(R.string.alert_chat_clear_success));
            return;
        }
        if (topUserEvent.isType()) {
            if (conversationListView.getAdapter().getCount() != 0) {
                TopEaseUser topEaseUser = new TopEaseUser();
                EMConversation emConversation = conversationListView.getItem(topUserEvent.getPostion());
                emConversation.setExtField(topUserEvent.getUsername());
                topEaseUser.setUsername(topUserEvent.getUsername());
                TopUserCache.getInstance(getContext()).saveData(topEaseUser);
                ShowToast.showShortToast(getString(R.string.text_top_chat_success));
            }
        } else {
            topMap.remove(topUserEvent.getUsername());
            TopUserCache.getInstance(getContext()).removeDataById(topUserEvent.getUsername());
            ShowToast.showShortToast(getString(R.string.text_cancel_top_user));
        }
        refresh();
    }

    @Subscribe(threadMode = ThreadMode.MAIN) //在ui线程执行
    public void onDataSynEvent(String event) {
        switch (event) {
            case GroupDetailsActivity.EVENT_GROUP_UPDATE:
                refresh();
                break;
            case EVENT_RESERVATION_SUCCESS:
                refresh();
                break;
            case EVENT_ADD_FRIENDS:
                iv_unread.setVisibility(View.VISIBLE);
                break;
        }
    }
}
